use std::borrow::Cow;

use thiserror::Error;

pub type IoErr = std::io::Error;

pub type AppErr = Error;

#[derive(Debug, Error)]
pub enum Error {

    #[error("io:{0}")]
    Io(#[from] IoErr),

    #[error("{0}")]
    Custom(Cow<'static, str>),

    #[error("timeout:{0}")]
    Timeout(&'static str),

    #[error("closed:{0}")]
    Closed(&'static str),

    #[error("proto:{0}")]
    Proto(&'static str),

    #[error("invalid:{0}")]
    Invalid(&'static str),
}

pub trait ErrConv<T> {
    
    fn conv(self) -> Result<T, AppErr>;
}

impl <T, E: std::error::Error> ErrConv<T> for Result<T, E> {

    fn conv(self) -> Result<T, AppErr> {
        match self {
            Ok(v) => Ok(v),
            Err(e) => Err(AppErr::Custom(Cow::Owned(e.to_string())))
        }
    }
}


impl <T> ErrConv<T> for Option<T> {

    fn conv(self) -> Result<T, AppErr> {
        match self {
            Some(v) => Ok(v),
            None => Err(AppErr::Custom(Cow::Borrowed("option is none")))
        }
    }
}

